package com.yubest.demo.advice;

import com.fasterxml.jackson.databind.JsonNode;
import com.yubest.demo.anno.SignProcess;
import com.yubest.demo.dto.Response;
import com.yubest.demo.util.JsonUtil;
import com.yubest.demo.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * @Author hweiyu
 * @Description
 * @Date 2021/3/10 16:56
 */
@ControllerAdvice
@Slf4j
public class MyResponseBodyAdvice implements ResponseBodyAdvice {

    @Value("${signKey:}")
    private String secret;

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        SignProcess process = methodParameter.getMethodAnnotation(SignProcess.class);
        //如果带有注解且标记为加签，测进行加签操作
        return null != process && process.sign();
    }

    /**
     * @param o
     * @param methodParameter
     * @param mediaType
     * @param aClass
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //如果是rest接口统一封装返回对象
        if (o instanceof Response) {
            Response res = (Response) o;
            //如果返回成功
            if (res.isOk()) {
                Object data = res.getData();
                if (null != data) {
                    JsonNode json = JsonUtil.beanToNode(data);
                    //仅处理object类型
                    if (json.isObject()) {
                        TreeMap<String, String> map = new TreeMap<>();
                        Iterator<Map.Entry<String, JsonNode>> fields = json.fields();
                        while(fields.hasNext()){
                            Map.Entry<String, JsonNode> entry = fields.next();
                            map.put(entry.getKey(), JsonUtil.toStr(entry.getValue()));
                        }
                        SignUtil.sign(map, secret);
                        return Response.success(map);
                    }
                }
            }
        }
        return o;
    }
}
